package com.ybl.store.backend.service.impl.deal;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ybl.store.backend.dao.entity.deal.DealProductDO;
import com.ybl.store.backend.dao.entity.deal.LogDealProductNumberDO;
import com.ybl.store.backend.dao.mapper.deal.DealProductMapper;
import com.ybl.store.backend.dao.mapper.deal.LogDealProductNumberMapper;
import com.ybl.store.backend.dto.UserInfoDTO;
import com.ybl.store.backend.dto.req.deal.DealProductUpdateReqDTO;
import com.ybl.store.backend.dto.req.deal.LogDealProductNumberSaveReqDTO;
import com.ybl.store.backend.dto.req.deal.LogDealProductNumberUpdateReqDTO;
import com.ybl.store.backend.dto.resp.deal.LogDealProductNumberExportRespDTO;
import com.ybl.store.backend.dto.resp.deal.LogDealProductNumberPageRespDTO;
import com.ybl.store.backend.service.deal.DealProductService;
import com.ybl.store.backend.service.deal.LogDealProductNumberService;
import com.ybl.store.backend.service.impl.customer.CustomerProductService;
import com.ybl.store.backend.service.store.ProductService;
import com.ybl.store.common.constant.UserPermission;
import com.ybl.store.common.context.UserContext;
import com.ybl.store.common.convention.errorcode.BaseErrorCode;
import com.ybl.store.common.convention.exception.ClientException;
import com.ybl.store.common.entity.ListRespDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

@Service
@RequiredArgsConstructor
@Transactional
public class LogDealProductNumberServiceImpl extends ServiceImpl<LogDealProductNumberMapper, LogDealProductNumberDO> implements LogDealProductNumberService {

    private final DealProductMapper dealProductMapper;
    
    private final DealProductService dealProductService;
    
    private final CustomerProductService customerProductService;
    
    private final ProductService productService;

    @Override
    public void saveLogDealProductNumber(LogDealProductNumberSaveReqDTO requestParam) {
        // 查询订单
        DealProductDO dealProductDO = dealProductMapper.selectById(requestParam.getDealProductId());
        if (dealProductDO == null) {
            throw new ClientException(BaseErrorCode.DEAL_PRODUCT_NULL_ERROR);
        }

        // 计算数量是否合法
        if (dealProductDO.getTotalNumber() - dealProductDO.getCurrentNumber() < requestParam.getNumber()) {
            throw new ClientException(BaseErrorCode.LOG_DEAL_PRODUCT_NUMBER_ERROR);
        }

        // 更新订单
        dealProductDO.setCurrentNumber(dealProductDO.getCurrentNumber() + requestParam.getNumber());
        dealProductDO.setDealStatus();
        dealProductService.updateDealProduct(BeanUtil.toBean(dealProductDO, DealProductUpdateReqDTO.class));
        
        // 更新顾客
        customerProductService.addNumber(dealProductDO.getCustomerId(), dealProductDO.getProductId(), requestParam.getNumber());
        
        // 更新货品
        productService.subNumber(dealProductDO.getProductId(), requestParam.getNumber());

        // 更新订单记录
        int result = baseMapper.insert(BeanUtil.toBean(requestParam, LogDealProductNumberDO.class));
        if (result < 1) {
            throw new ClientException(BaseErrorCode.LOG_DEAL_PRODUCT_SAVE_ERROR);
        }
    }

    @Override
    public void deleteLogDealProductNumber(Long id) {
        // 查询订单和订单记录
        LogDealProductNumberDO logDealProductNumberDO = baseMapper.selectById(id);
        if (logDealProductNumberDO == null) {
            throw new ClientException(BaseErrorCode.LOG_DEAL_PRODUCT_NULL_ERROR);
        }
        DealProductDO dealProductDO = dealProductMapper.selectById(logDealProductNumberDO.getDealProductId());
        if (dealProductDO == null) {
            throw new ClientException(BaseErrorCode.DEAL_PRODUCT_NULL_ERROR);
        }

        // 更新订单
        dealProductDO.setCurrentNumber(dealProductDO.getCurrentNumber() - logDealProductNumberDO.getNumber());
        dealProductDO.setDealStatus();
        dealProductService.updateDealProduct(BeanUtil.toBean(dealProductDO, DealProductUpdateReqDTO.class));

        // 更新顾客
        customerProductService.subNumber(dealProductDO.getCustomerId(), dealProductDO.getProductId(), logDealProductNumberDO.getNumber());

        // 更新货品
        productService.addNumber(dealProductDO.getProductId(), logDealProductNumberDO.getNumber());

        // 更新订单记录
        int result = baseMapper.deleteById(id);
        if (result < 1) {
            throw new ClientException(BaseErrorCode.LOG_DEAL_PRODUCT_DELETE_ERROR);
        }
    }

    @Override
    public void updateLogDealProductNumber(LogDealProductNumberUpdateReqDTO requestParam) {
        // 查询订单和订单记录
        DealProductDO dealProductDO = dealProductMapper.selectById(requestParam.getDealProductId());
        if (dealProductDO == null) {
            throw new ClientException(BaseErrorCode.DEAL_PRODUCT_NULL_ERROR);
        }
        LogDealProductNumberDO logDealProductNumberDO = baseMapper.selectById(requestParam.getId());
        if (logDealProductNumberDO == null) {
            throw new ClientException(BaseErrorCode.LOG_DEAL_PRODUCT_NULL_ERROR);
        }

        // 计算数量是否合法
        if (dealProductDO.getTotalNumber() - dealProductDO.getCurrentNumber() + logDealProductNumberDO.getNumber() < requestParam.getNumber()) {
            throw new ClientException(BaseErrorCode.LOG_DEAL_PRODUCT_NUMBER_ERROR);
        }

        // 更新订单
        dealProductDO.setCurrentNumber(dealProductDO.getCurrentNumber() - logDealProductNumberDO.getNumber() + requestParam.getNumber());
        dealProductDO.setDealStatus();
        dealProductService.updateDealProduct(BeanUtil.toBean(dealProductDO, DealProductUpdateReqDTO.class));

        // 更新顾客商品
        customerProductService.subNumber(dealProductDO.getCustomerId(), dealProductDO.getProductId(), logDealProductNumberDO.getNumber());
        customerProductService.addNumber(dealProductDO.getCustomerId(), dealProductDO.getProductId(), requestParam.getNumber());

        // 更新货品
        productService.addNumber(dealProductDO.getProductId(), logDealProductNumberDO.getNumber());
        productService.subNumber(dealProductDO.getProductId(), requestParam.getNumber());

        int result = baseMapper.updateById(BeanUtil.toBean(requestParam, LogDealProductNumberDO.class));
        if (result < 1) {
            throw new ClientException(BaseErrorCode.LOG_DEAL_PRODUCT_UPDATE_ERROR);
        }
    }

    @Override
    public ListRespDTO<LogDealProductNumberPageRespDTO> pageLogDealProductNumber(Integer pn, Integer ps, Long dealProductId, Long storeId, Long clerkId, Long customerId, Long productId, String startTime, String endTime) {
        UserInfoDTO userInfoDTO = UserContext.get();
        if (!Objects.equals(userInfoDTO.getPermission(), UserPermission.ADMIN)) {
            storeId = userInfoDTO.getStoreId();
            clerkId = userInfoDTO.getId();
        }
        boolean timeCondition = Objects.nonNull(startTime) && Objects.nonNull(endTime);

        Page<LogDealProductNumberPageRespDTO> page = new Page<>(pn, ps);
        QueryWrapper<LogDealProductNumberDO> queryWrapper = Wrappers.query(LogDealProductNumberDO.class)
                .eq(Objects.nonNull(dealProductId), "log_deal.deal_product_id", dealProductId)
                .eq(Objects.nonNull(storeId), "deal.store_id", storeId)
                .eq(Objects.nonNull(clerkId), "deal.clerk_id", clerkId)
                .eq(Objects.nonNull(customerId), "deal.customer_id", customerId)
                .eq(Objects.nonNull(productId), "deal.product_id", productId)
                .between(timeCondition, "log_deal.deal_time", startTime, endTime)
                .eq("log_deal.del_flag", 0)
                .orderByDesc("log_deal.deal_time");
        List<LogDealProductNumberPageRespDTO> logDealProductNumberPageRespDTOList = baseMapper.pageLogDealProductNumber(page, queryWrapper);

        queryWrapper = Wrappers.query(LogDealProductNumberDO.class)
                .eq(Objects.nonNull(dealProductId), "log_deal.deal_product_id", dealProductId)
                .eq(Objects.nonNull(storeId), "deal.store_id", storeId)
                .eq(Objects.nonNull(clerkId), "deal.clerk_id", clerkId)
                .eq(Objects.nonNull(customerId), "deal.customer_id", customerId)
                .eq(Objects.nonNull(productId), "deal.product_id", productId)
                .between(timeCondition, "log_deal.deal_time", startTime, endTime)
                .eq("log_deal.del_flag", 0);
        Long total = baseMapper.count(queryWrapper);

        return ListRespDTO.<LogDealProductNumberPageRespDTO>builder()
                .total(total)
                .items(logDealProductNumberPageRespDTOList)
                .build();
    }

    @Override
    public List<LogDealProductNumberExportRespDTO> export() {
        return baseMapper.export();
    }
}
